package com.parser;

import com.lexicalAnalyzer.ISymbolTable;import com.lexicalAnalyzer.OperatorType;import com.lexicalAnalyzer.Scanner;import com.lexicalAnalyzer.SymbolTable;import com.lexicalAnalyzer.SymbolTableEntry;import com.lexicalAnalyzer.Token;import com.lexicalAnalyzer.TokenCode;

import java.io.IOException;
import java.lang.String;import java.util.ArrayList;

public abstract class ParserBase {

	protected Scanner m_lexan;			// Lexical analyzer
	protected SymbolTable m_symTab;		// symbol table
	protected Token m_currentToken;		// Current token
	protected Code m_code;				// Three Address Code
	protected int m_totalErrors;		// Total number of errors
	
	protected abstract boolean tokenCodeIn(TokenCode tc, TokenCode[] plist); // Is the given tokencode in the list
	protected abstract void recover(TokenCode[] plist); // keep asking for tokens until token is found in the list
	protected abstract void getToken(); 				// ask lexical analyzer for next token
	protected abstract Token match(TokenCode tc) throws TokenMismatchException; // Walk over tokencode tc. If not a match; report an error.
	protected abstract void setError(String err); 		// sets the appropriate error message
	
	/**
	 * Gets the {@link TokenCode} of the current token.
	 * @return The current token code
	 */
	protected TokenCode getTokenCode()
    {
        return m_currentToken.getTokenCode();


        /*try
        {
            return m_currentToken.getTokenCode();
        }
        catch (IOException Ex)
        {
            Ex.printStackTrace();
        }
		if (this.m_currentToken != null)
		{
			return m_currentToken.getTokenCode();
		}
		return TokenCode.EOF;  */
	}

	/* Parsing methods */
	protected abstract void parseArrayReference();
	protected abstract SymbolTableEntry parseFactorRest(SymbolTableEntry prevEntry);
	protected abstract SymbolTableEntry parseFactor();
	protected abstract SymbolTableEntry parseTermRest(SymbolTableEntry prevEntry);
	protected abstract SymbolTableEntry parseTerm();
	protected abstract SymbolTableEntry parseSimpleExpressionAddop(SymbolTableEntry prevEntry);
	protected abstract SymbolTableEntry parseSimpleExpressionRelop(SymbolTableEntry prevEntry);
	protected abstract void parseSign();
    protected abstract SymbolTableEntry parseSimpleExpression();
	protected abstract void parseExpressionListMore(ArrayList<SymbolTableEntry> eList);
	protected abstract void parseExpressionList(SymbolTableEntry prevEntry);
	protected abstract SymbolTableEntry parseExpression();
	protected abstract void parseIdOrProcedureStatement(SymbolTableEntry prevEntry);
	protected abstract void parseWhileStatement();
	protected abstract void parseIfStatement();
	protected abstract void parseStatement();
	protected abstract void parseStatementListMore();
	protected abstract void parseStatementList();
	protected abstract void parseOptionalStatements();
	protected abstract void parseCompoundStatement();
	protected abstract void parseStandardType();
	protected abstract void parseType();
	protected abstract void parseIdentifierListAndType(boolean subProgramHead);
	protected abstract void parseIdentifierListMore(ArrayList<SymbolTableEntry> eList);
	protected abstract void parseIdentifierList(ArrayList<SymbolTableEntry> eList);
	protected abstract void parseParameterListMore();
	protected abstract void parseParameterList();
	protected abstract void parseArguments();
	protected abstract void parseSubprogramHead();
	protected abstract void parseSubprogramDeclarations();
	protected abstract void parseSubprogramDeclaration();
	protected abstract void parseDeclarations(boolean subProgramHead);
	protected abstract SymbolTableEntry parseProgramDefinition();
	protected abstract void parseProgram();
	
	/* Code generation */
	protected abstract CodeOperator opToCode(OperatorType op);
	protected abstract SymbolTableEntry newTemp();
	protected abstract SymbolTableEntry newLabel();

	/* Public methods */
	public ParserBase() {
		super();
	}
	
	public abstract void parse();
	public abstract ISymbolTable getSymbolTable();

	/**
	 * Gets the total number of errors in the source file.
	 * @return The total number of errors in the source file
	 */
	public int totalErrors() {
		return m_totalErrors;
	}

	/**
	 * Gets the three address code generated from the source file.
	 * @return The three address code.
	 */
	public String getTacCode() {
		return this.m_code.toString();
	}
}